// VS_BEGIN
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aCoord;

out vec2 g_coord;

void main() {
    gl_Position = vec4(aPos, 1.0f);
    g_coord = aCoord;
}
// VS_END

// FS_BEGIN
#version 330 core

in vec2 g_coord;

uniform sampler2D u_cameraPositionMap;
uniform samplerCube u_lightDepthMap;
uniform vec3 u_lightPos;

out vec4 FragColor;

uniform float u_zFar;
uniform float u_bias;
uniform float u_sample = 2.0f;

float g_offset = 0.005f;

float CalShadow(vec3 worldPos) {
    float shadowValue = 0.0f;
    vec3 dir = normalize(worldPos - u_lightPos);
    float sampleCount = 0;
    if (u_sample == 1.0f) {
        float depth = texture(u_lightDepthMap, dir).r;
        if (distance(worldPos, u_lightPos) > depth * u_zFar + u_bias) {
            shadowValue += 1.0f;
        }
        sampleCount += 1.0f;
    } else {
        for (float x = -g_offset; x <= g_offset; x += g_offset / u_sample) {
            for (float y = -g_offset; y <= g_offset; y += g_offset / u_sample) {
                for (float z = -g_offset; z <= g_offset; z += g_offset / u_sample) {
                    float depth = texture(u_lightDepthMap, dir + vec3(x, y, z)).r;
                    if (distance(worldPos, u_lightPos) > depth * u_zFar + u_bias) {
                        shadowValue += 1.0f;
                    }
                    sampleCount += 1.0f;
                }
            }
        }
    }
    return shadowValue / sampleCount;
}

void main() {
    vec3 worldPos = vec3(texture(u_cameraPositionMap, g_coord));
    if (worldPos == vec3(0.0f)) {
        FragColor = vec4(vec3(0.0f), 0.0f);
    } else {
        FragColor = vec4(vec3(0.0f), CalShadow(worldPos));
    }
}
// FS_END